#!/usr/bin/python3
# ******************************************************************************
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# ******************************************************************************/
import re
import os

from typing import List
from ceres.conf.constant import CommandExitCode
from ceres.function.log import LOGGER
from ceres.function.util import execute_shell_command

__all__ = ["SetRepoManage"]


class SetRepoManage:
    def set_repo(self, data: dict) -> int:
        """
        Save the repo source to local, and do simple verification.

        Args:
            data (dict): e.g
                {
                    "repo_info": {
                        "name": "string",
                        "dest": "save location",
                        "repo_content": "repo source info"
                    },
                    "check_items": ["string"],
                    "check": false
                }

        Returns:
            bool: operation result of repo set
        """
        repo_path = data.get("repo_info").get("dest")
        if re.match(r"/etc/yum.repos.d/[\w-]+.repo$", repo_path) is None:
            LOGGER.debug('Incorrect repo save path.')
            return False

        content = data.get("repo_info").get("repo_content")
        repo_id_list = re.findall(r'\[([^\]]+)\]', re.sub(r'^\s*#.*$', '', content, flags=re.MULTILINE))
        if not repo_id_list:
            LOGGER.warning("Failed to extract repo id information, please check the repo content.")
            return False

        with open(repo_path, 'w', encoding='utf8') as repo_file:
            repo_file.write(content)
            LOGGER.info(f'Repo source {data.get("repo_info").get("name")} has been saved to {repo_path}.')

        if self._validate_repo_source(repo_id_list):
            LOGGER.info('Repo source set succeed.')
            return True
        os.remove(repo_path)
        LOGGER.warning("Repo source can't be used, it has been deleted.")
        return False

    @staticmethod
    def _validate_repo_source(repo_id_list: List[str]) -> bool:
        """
        A sample validate which repo can used by yum.

        Args:
            repo_id(list): repo id list

        Returns:
            bool
        """

        def query_repo_info(repo_id: str) -> bool:
            """
            Verify the validity of the repo source by querying the repo source information.

            Args:
                repo_id(str)

            Returns:
                bool
            """
            code, _, stderr = execute_shell_command([f"dnf repoinfo --repo {repo_id}"])
            if code == CommandExitCode.SUCCEED:
                return True
            LOGGER.warning(f"Failed to query repo information with repo id {repo_id}.")
            LOGGER.warning(stderr)
            return False

        validate_result = True
        for repo_id in repo_id_list:
            validate_result = validate_result and query_repo_info(repo_id)
        return validate_result
